
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Stream API中集合并行处理的原理 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Stream API中集合并行处理的原理 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">Java并行流实现其并行计算的核心思想是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">并行流的实现基于“分而治之”的思想，其主要流程包括三个步骤：1. 任务分解（利用 Spliterator 将数据拆分）；2. 任务分配（使用 ForkJoinPool 将子任务分配到不同线程）；3. 结果合并（将各线程的计算结果归并为最终结果）。</div>
          </div>
          <div class="card-source">来源: 并行流概述 -> 2. 核心设计思想</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">顺序流与并行流在执行方式和线程管理上有何主要区别？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">执行方式上，顺序流在单个线程中按顺序逐个处理元素，而并行流将数据分块后分配给多个线程同时处理。线程管理上，顺序流通常运行在调用它的线程上，而并行流则使用公共的 ForkJoinPool 来管理工作线程。</div>
          </div>
          <div class="card-source">来源: 并行流概述 -> 1. 并行流与顺序流的区别</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">并行流默认使用的线程池是什么？其并行度通常如何确定？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">并行流的底层线程管理依赖于Java的 ForkJoinPool。默认情况下，该线程池的并行度与系统的可用处理器数量一致，这个数量通常通过 `Runtime.getRuntime().availableProcessors()` 方法获取。</div>
          </div>
          <div class="card-source">来源: 并行流概述 -> 3. 默认线程池与并行度</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">Fork/Join框架中的“工作窃取算法”是如何工作的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">在ForkJoinPool中，每个工作线程维护一个双端任务队列。当某个线程完成了自己队列中的所有任务后，它会从其他线程的任务队列的尾部“窃取”一个任务来执行。这种设计减少了线程间的竞争，并提高了整体的线程利用率。</div>
          </div>
          <div class="card-source">来源: Fork/Join框架基础 -> 1. Fork/Join 框架的核心组件</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在Java并行流中，Spliterator（可分割迭代器）扮演了什么关键角色？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Spliterator 的核心作用是实现数据源的高效分割。当一个并行流被创建时，它会使用 Spliterator 将数据源递归地拆分成多个更小的部分，这些部分随后可以作为独立的子任务被分配到不同的线程中进行并行处理。</div>
          </div>
          <div class="card-source">来源: Spliterator的角色</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">Spliterator 接口中哪个方法是实现任务拆分以支持并行处理的核心？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`trySplit()` 是 Spliterator 的核心方法之一。该方法用于将当前的 Spliterator 拆分为两个部分，它会返回一个代表拆分后一部分数据的新 Spliterator，而原始的 Spliterator 则处理剩余部分。这个机制是并行流能够将任务分割的基础。</div>
          </div>
          <div class="card-source">来源: Spliterator的角色 -> 1. Spliterator 的核心方法</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">工作原理</div>
          <div class="card-question">请简述一个并行流从数据源到最终结果的三个核心工作步骤。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">工作原理</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. **数据源的分割**：通过 `Spliterator` 将数据源递归地拆分成更小的子数据块。 2. **Fork/Join 框架的任务调度**：每个数据块被视为一个任务，由 `ForkJoinPool` 线程池管理，并通过“工作窃取算法”实现负载均衡。 3. **结果合并（Join）**：当所有子任务处理完成后，框架会逐步将各线程的部分结果汇总，形成整体的最终结果。</div>
          </div>
          <div class="card-source">来源: 工作原理 -> 2. 工作步骤与详细剖析</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">为什么说并行流不适合用于处理IO密集型操作？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为IO密集型操作（如文件读写或数据库查询）的性能瓶颈主要在于IO等待，而不是CPU计算。在这种场景下，使用并行流进行任务拆分和线程管理的开销可能会超过其带来的性能收益，甚至因为线程竞争IO资源而降低效率。</div>
          </div>
          <div class="card-source">来源: 并行流概述 -> 4. 并行流的适用场景</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在Java中，有哪两种主要方式可以生成并行流？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. **使用 `parallelStream()` 方法**：这是集合类（如List, Set）提供的方法，可以直接从集合创建一个并行流。 2. **使用 `Stream` 的 `parallel()` 方法**：该方法可以将一个已有的顺序流（Sequential Stream）转换为并行流。</div>
          </div>
          <div class="card-source">来源: 并行流的生成方式 -> 1. 并行流的生成方式</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
